import {
  Controller,
  Get,
  Post,
  Put,
  Delete,
  Patch,
  Body,
  Param,
  Query,
  UseGuards,
  UseInterceptors,
  UploadedFile,
  UploadedFiles,
  HttpCode,
  HttpStatus
} from '@nestjs/common'
import { FileInterceptor, FilesInterceptor } from '@nestjs/platform-express'
import { ApiTags, ApiOperation, ApiConsumes } from '@nestjs/swagger'
import { ContentService } from './content.service'
import {
  CreateContentDto,
  UpdateContentDto,
  QueryContentDto,
  ContentResponseDto,
  ContentStatsDto,
  BulkContentOperationDto,
  PublishContentDto,
  ContentVersionDto
} from '../../common/dto/content.dto'
import { PaginatedResponseDto } from '../../common/dto/pagination.dto'
import { JwtAuthGuard, RolesGuard, PermissionsGuard } from '../../common/guards/auth.guard'
import { Auth, Public, ContentAuth } from '../../common/decorators/auth.decorator'
import { CurrentUser } from '../../common/decorators/user.decorator'
import type { UserInfo } from '../../common/decorators/user.decorator'
import {
  ApiDoc,
  ApiPagination,
  ApiCreate,
  ApiUpdate,
  ApiDelete,
  ApiFindOne,
  ApiBatch,
  ApiUpload,
  ApiStats,
  ApiExport,
  ApiImport
} from '../../common/decorators/api.decorator'
import { ResponseMessage, Cache, SkipCache } from '../../common/decorators/response.decorator'
import { FileValidationPipe } from '../../common/pipes/validation.pipe'
import { LoggerService } from '../../common/logger/logger.service'
import * as path from 'path'

@ApiTags('内容管理')
@Controller('content')
export class ContentController {
  constructor(
    private readonly contentService: ContentService,
    private readonly logger: LoggerService
  ) {}

  @Post()
  @ContentAuth.ArticleCreate()
  @ApiCreate(ContentResponseDto, '创建内容', '创建新的文章或页面内容')
  @ResponseMessage('内容创建成功')
  async create(
    @Body() createContentDto: CreateContentDto,
    @CurrentUser() currentUser: UserInfo
  ): Promise<ContentResponseDto> {
    this.logger.info('创建内容请求', {
      author: currentUser.id,
      title: createContentDto.title,
      type: createContentDto.type,
      status: createContentDto.status
    })

    const content = await this.contentService.create(createContentDto, currentUser.id)

    this.logger.info('内容创建成功', {
      author: currentUser.id,
      contentId: content.id,
      title: content.title,
      type: content.type
    })

    return content
  }

  @Get()
  @Public()
  @ApiPagination(ContentResponseDto, '获取内容列表', '分页获取内容列表，支持多种筛选条件')
  @Cache(300) // 缓存5分钟
  async findAll(@Query() queryDto: QueryContentDto): Promise<PaginatedResponseDto<ContentResponseDto>> {
    this.logger.debug('获取内容列表请求', {
      query: queryDto
    })

    return this.contentService.findAll(queryDto)
  }

  @Get('drafts')
  @ContentAuth.ArticleManage()
  @ApiPagination(ContentResponseDto, '获取草稿列表', '获取当前用户的草稿内容列表')
  @Cache(60) // 缓存1分钟
  async getDrafts(
    @Query() queryDto: QueryContentDto,
    @CurrentUser() currentUser: UserInfo
  ): Promise<PaginatedResponseDto<ContentResponseDto>> {
    this.logger.debug('获取草稿列表请求', {
      author: currentUser.id,
      query: queryDto
    })

    return this.contentService.findDrafts(queryDto, currentUser.id)
  }

  @Get('published')
  @Public()
  @ApiDoc({
    summary: '获取已发布内容',
    description: '获取所有已发布的内容列表'
  })
  @Cache(600) // 缓存10分钟
  async getPublished(@Query() queryDto: QueryContentDto): Promise<PaginatedResponseDto<ContentResponseDto>> {
    this.logger.debug('获取已发布内容请求', {
      query: queryDto
    })

    return this.contentService.findPublished(queryDto)
  }

  @Get('stats')
  @ContentAuth.ArticleManage()
  @ApiStats('获取内容统计', '获取内容相关的统计数据')
  @Cache(600) // 缓存10分钟
  async getStats(@CurrentUser() currentUser: UserInfo): Promise<ContentStatsDto> {
    this.logger.debug('获取内容统计请求', {
      operator: currentUser.id
    })

    return this.contentService.getStats(currentUser.id)
  }

  @Get('search')
  @Public()
  @ApiDoc({
    summary: '搜索内容',
    description: '全文搜索内容'
  })
  @Cache(300) // 缓存5分钟
  async search(
    @Query('q') query: string,
    @Query('type') type?: string,
    @Query('category') category?: string,
    @Query('page') page: number = 1,
    @Query('limit') limit: number = 20
  ): Promise<PaginatedResponseDto<ContentResponseDto>> {
    this.logger.debug('搜索内容请求', {
      query,
      type,
      category,
      page,
      limit
    })

    return this.contentService.search({
      query,
      type,
      category,
      page,
      limit
    })
  }

  @Get(':id')
  @Public()
  @ApiFindOne(ContentResponseDto, '获取内容详情', '根据ID获取内容详细信息')
  @Cache(300) // 缓存5分钟
  async findOne(
    @Param('id') id: string,
    @Query('includeViews') includeViews: boolean = true
  ): Promise<ContentResponseDto> {
    this.logger.debug('获取内容详情请求', {
      contentId: id,
      includeViews
    })

    const content = await this.contentService.findById(id, includeViews)

    if (includeViews) {
      // 异步增加浏览量
      this.contentService.incrementViews(id).catch(error => {
        this.logger.error(
          '增加浏览量失败',
          error.stack,
          JSON.stringify({
            contentId: id,
            error: error.message
          })
        )
      })
    }

    return content
  }

  @Put(':id')
  @ContentAuth.ArticleEdit()
  @ApiUpdate(ContentResponseDto, '更新内容', '更新指定内容的信息')
  @ResponseMessage('内容更新成功')
  @SkipCache() // 跳过缓存
  async update(
    @Param('id') id: string,
    @Body() updateContentDto: UpdateContentDto,
    @CurrentUser() currentUser: UserInfo
  ): Promise<ContentResponseDto> {
    this.logger.info('更新内容请求', {
      operator: currentUser.id,
      contentId: id,
      data: updateContentDto
    })

    const content = await this.contentService.update(id, updateContentDto, currentUser.id)

    this.logger.info('内容更新成功', {
      operator: currentUser.id,
      contentId: id,
      title: content.title,
      updatedFields: Object.keys(updateContentDto)
    })

    return content
  }

  @Delete(':id')
  @ContentAuth.ArticleDelete()
  @ApiDelete('删除内容', '删除指定ID的内容')
  @HttpCode(HttpStatus.NO_CONTENT)
  @ResponseMessage('内容删除成功')
  @SkipCache() // 跳过缓存
  async remove(@Param('id') id: string, @CurrentUser() currentUser: UserInfo): Promise<void> {
    this.logger.info('删除内容请求', {
      operator: currentUser.id,
      contentId: id
    })

    await this.contentService.remove(id, currentUser.id)

    this.logger.info('内容删除成功', {
      operator: currentUser.id,
      contentId: id
    })
  }

  @Patch(':id/publish')
  @ContentAuth.ArticlePublish()
  @ApiDoc({
    summary: '发布内容',
    description: '发布指定的内容'
  })
  @ResponseMessage('内容发布成功')
  @SkipCache() // 跳过缓存
  async publish(
    @Param('id') id: string,
    @Body() publishDto: PublishContentDto,
    @CurrentUser() currentUser: UserInfo
  ): Promise<ContentResponseDto> {
    this.logger.info('发布内容请求', {
      operator: currentUser.id,
      contentId: id,
      publishAt: publishDto.publishAt
    })

    const content = await this.contentService.publish(id, publishDto, currentUser.id)

    this.logger.info('内容发布成功', {
      operator: currentUser.id,
      contentId: id,
      title: content.title,
      publishAt: content.publishedAt
    })

    return content
  }

  @Patch(':id/unpublish')
  @ContentAuth.ArticlePublish()
  @ApiDoc({
    summary: '取消发布',
    description: '取消发布指定的内容'
  })
  @ResponseMessage('内容已取消发布')
  @SkipCache() // 跳过缓存
  async unpublish(@Param('id') id: string, @CurrentUser() currentUser: UserInfo): Promise<ContentResponseDto> {
    this.logger.info('取消发布内容请求', {
      operator: currentUser.id,
      contentId: id
    })

    const content = await this.contentService.unpublish(id, currentUser.id)

    this.logger.info('内容取消发布成功', {
      operator: currentUser.id,
      contentId: id,
      title: content.title
    })

    return content
  }

  @Post(':id/duplicate')
  @ContentAuth.ArticleCreate()
  @ApiDoc({
    summary: '复制内容',
    description: '复制指定的内容创建新内容'
  })
  @ResponseMessage('内容复制成功')
  async duplicate(
    @Param('id') id: string,
    @Body() body: { title?: string },
    @CurrentUser() currentUser: UserInfo
  ): Promise<ContentResponseDto> {
    this.logger.info('复制内容请求', {
      operator: currentUser.id,
      sourceContentId: id,
      newTitle: body.title
    })

    const content = await this.contentService.duplicate(id, body.title, currentUser.id)

    this.logger.info('内容复制成功', {
      operator: currentUser.id,
      sourceContentId: id,
      newContentId: content.id,
      newTitle: content.title
    })

    return content
  }

  @Get(':id/versions')
  @ContentAuth.ArticleManage()
  @ApiDoc({
    summary: '获取内容版本历史',
    description: '获取指定内容的版本历史记录'
  })
  @Cache(300) // 缓存5分钟
  async getVersions(
    @Param('id') id: string,
    @Query('page') page: number = 1,
    @Query('limit') limit: number = 20,
    @CurrentUser() currentUser: UserInfo
  ): Promise<PaginatedResponseDto<ContentVersionDto>> {
    this.logger.debug('获取内容版本历史请求', {
      operator: currentUser.id,
      contentId: id,
      page,
      limit
    })

    return this.contentService.getVersions(id, { page, limit }, currentUser.id)
  }

  @Post(':id/restore/:versionId')
  @ApiDoc({
    summary: '恢复内容版本',
    description: '将内容恢复到指定版本'
  })
  @ContentAuth.ArticleEdit()
  async restoreVersion(
    @Param('id') id: string,
    @Param('versionId') versionId: string,
    @CurrentUser() currentUser: UserInfo
  ) {
    // TODO: 实现版本恢复功能
    return {
      message: '版本恢复成功',
      data: { id, versionId }
    }
  }

  @Post(':id/upload')
  @UseInterceptors(
    FilesInterceptor('files', 10, {
      limits: {
        fileSize: 10 * 1024 * 1024 // 10MB
      },
      fileFilter: (req, file, callback) => {
        // 允许的文件类型
        const allowedTypes = /jpeg|jpg|png|gif|pdf|doc|docx|txt/
        const extname = allowedTypes.test(path.extname(file.originalname).toLowerCase())
        const mimetype = allowedTypes.test(file.mimetype)

        if (mimetype && extname) {
          return callback(null, true)
        } else {
          callback(new Error('不支持的文件类型'), false)
        }
      }
    })
  )
  @ApiUpload('上传媒体文件', '为内容上传相关的媒体文件')
  @ContentAuth.ArticleEdit()
  async uploadMedia(
    @Param('id') id: string,
    @UploadedFiles() files: Express.Multer.File[],
    @CurrentUser() currentUser: UserInfo
  ): Promise<{ files: Array<{ url: string; name: string; size: number }> }> {
    this.logger.info('上传媒体文件请求', {
      operator: currentUser.id,
      contentId: id,
      fileCount: files.length,
      fileSizeLimit: 10 * 1024 * 1024 // 10MB
    })

    const uploadedFiles = await this.contentService.uploadMedia(id, files, currentUser.id)

    this.logger.info('媒体文件上传成功', {
      operator: currentUser.id,
      contentId: id,
      uploadedCount: uploadedFiles.uploaded
    })

    return {
      files: uploadedFiles.files.map(file => ({
        url: file.url,
        name: file.filename,
        size: file.size
      }))
    }
  }

  @Post('batch')
  @ContentAuth.ArticleManage()
  @ApiBatch('批量操作内容', '批量创建、更新、发布或删除内容')
  @ResponseMessage('批量操作完成')
  @SkipCache() // 跳过缓存
  async batchOperation(
    @Body() batchDto: BulkContentOperationDto,
    @CurrentUser() currentUser: UserInfo
  ): Promise<{
    success: number
    failed: number
    errors: Array<{ index: number; error: string }>
  }> {
    this.logger.info('批量操作内容请求', {
      operator: currentUser.id,
      operation: batchDto.operation,
      count: batchDto.items.length
    })

    const result = await this.contentService.batchOperation(batchDto, currentUser.id)

    this.logger.info('批量操作内容完成', {
      operator: currentUser.id,
      operation: batchDto.operation,
      success: result.success,
      failed: result.failed
    })

    return result
  }

  @Post('export')
  @ApiExport('导出内容', '导出内容数据为Excel或CSV格式')
  @ContentAuth.ArticleEdit()
  async exportContent(
    @Body() exportDto: any,
    @CurrentUser() currentUser: UserInfo
  ): Promise<{ downloadUrl: string; filename: string }> {
    this.logger.info('导出内容请求', {
      operator: currentUser.id,
      exportType: exportDto.format,
      filters: exportDto.filters
    })

    const result = await this.contentService.exportContent(exportDto, currentUser.id)

    this.logger.info('内容导出成功', {
      operator: currentUser.id,
      filename: result.filename,
      fileSize: result.size
    })

    return {
      downloadUrl: result.url,
      filename: result.filename
    }
  }

  @Post('import')
  @UseInterceptors(FileInterceptor('file'))
  @ContentAuth.ArticleManage()
  @ApiImport('导入内容数据', '从Excel或CSV文件导入内容数据')
  @ApiConsumes('multipart/form-data')
  @ResponseMessage('内容数据导入完成')
  async importContent(
    @UploadedFile(new FileValidationPipe())
    file: Express.Multer.File,
    @CurrentUser() currentUser: UserInfo
  ): Promise<{
    total: number
    success: number
    failed: number
    errors: Array<{ row: number; error: string }>
  }> {
    this.logger.info('导入内容数据请求', {
      operator: currentUser.id,
      filename: file.originalname,
      fileSize: file.size
    })

    const result = await this.contentService.importContent(file, currentUser.id)

    this.logger.info('内容数据导入完成', {
      operator: currentUser.id,
      total: result.total,
      success: result.success,
      failed: result.failed
    })

    return result
  }

  @Get(':id/related')
  @Public()
  @ApiDoc({
    summary: '获取相关内容',
    description: '获取与指定内容相关的其他内容'
  })
  @Cache(600) // 缓存10分钟
  async getRelatedContent(@Param('id') id: string, @Query('limit') limit: number = 5): Promise<ContentResponseDto[]> {
    this.logger.debug('获取相关内容请求', {
      contentId: id,
      limit
    })

    return this.contentService.getRelatedContent(id, limit)
  }

  @Post(':id/like')
  @ContentAuth.ArticleManage()
  @ApiDoc({
    summary: '点赞内容',
    description: '为指定内容点赞'
  })
  @ResponseMessage('点赞成功')
  async likeContent(
    @Param('id') id: string,
    @CurrentUser() currentUser: UserInfo
  ): Promise<{ liked: boolean; likesCount: number }> {
    this.logger.info('点赞内容请求', {
      userId: currentUser.id,
      contentId: id
    })

    const result = await this.contentService.toggleLike(id, currentUser.id)

    this.logger.info('点赞操作完成', {
      userId: currentUser.id,
      contentId: id,
      liked: result.liked,
      likesCount: result.likesCount
    })

    return result
  }

  @Post(':id/bookmark')
  @ContentAuth.ArticleManage()
  @ApiDoc({
    summary: '收藏内容',
    description: '收藏或取消收藏指定内容'
  })
  @ResponseMessage('收藏操作成功')
  async bookmarkContent(
    @Param('id') id: string,
    @CurrentUser() currentUser: UserInfo
  ): Promise<{ bookmarked: boolean }> {
    this.logger.info('收藏内容请求', {
      userId: currentUser.id,
      contentId: id
    })

    const result = await this.contentService.toggleBookmark(id, currentUser.id)

    this.logger.info('收藏操作完成', {
      userId: currentUser.id,
      contentId: id,
      bookmarked: result.bookmarked
    })

    return result
  }

  @Get('user/:userId')
  @Public()
  @ApiDoc({
    summary: '获取用户内容',
    description: '获取指定用户发布的内容列表'
  })
  @Cache(300) // 缓存5分钟
  async getUserContent(
    @Param('userId') userId: string,
    @Query() queryDto: QueryContentDto
  ): Promise<PaginatedResponseDto<ContentResponseDto>> {
    this.logger.debug('获取用户内容请求', {
      userId,
      query: queryDto
    })

    return this.contentService.findByAuthor(userId, queryDto)
  }
}
